﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using RAP.Framework.Libary.Utils;

namespace RAP.Framework.Libary.JSONSocket
{
  /// <summary>
  /// 基于JSON协议的Socket客户端/服务端
  /// </summary>
  public class SocketJSON : IDisposable
  {
    protected Socket _socket = null;

    /// <summary>
    /// 服务端IP
    /// </summary>
    public string ServerIP { get; set; }

    /// <summary>
    /// 连接端口
    /// </summary>
    public int Port { get; set; }

    /// <summary>
    /// Socket的状态，0：client，1：server
    /// </summary>
    public int State { get; private set; }

    /// <summary>
    /// 发生错误的事件
    /// </summary>
    public event Action<Exception> OnError;

    /// <summary>
    /// 当数据到达的事件
    /// </summary>
    public event Action<IDictionary> OnDataArrived;

    /// <summary>
    /// 触发发生错误的事件
    /// </summary>
    /// <param name="exc"></param>
    protected void FireError(Exception exc)
    {
      if (this.OnError != null)
      {
        this.OnError.Invoke(exc);
      }
    }

    /// <summary>
    /// 触发数据到达的事件
    /// </summary>
    /// <param name="json"></param>
    protected void FireDataArrived(string json)
    {
      if (this.OnDataArrived != null)
      {
        try
        {
          this.OnDataArrived.Invoke(json.ToDictionary());
        }
        catch (Exception exc)
        {
          this.FireError(new Exception($"JSON数据格式错误：{json}", exc));
        }

      }
    }

    /// <summary>
    /// 是否已连接到服务端
    /// </summary>
    public bool Connected { get; protected set; }

    protected IList<Socket> _clientSockets = null;

    /// <summary>
    /// 作为服务端开始侦听
    /// </summary>
    /// <returns></returns>
    public bool StartListen(int maxListenQueue = 3)
    {
      this.Close();
      this.State = 1;
      if (_clientSockets == null)
      {
        _clientSockets = new List<Socket>();
      }
      _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      _socket.Bind(new IPEndPoint(IPAddress.Parse(this.ServerIP), this.Port));//绑定IP地址：端口
      _socket.Listen(maxListenQueue);//设定最多 maxListenQueue 个排队连接请求
      var thread = new Thread(new ThreadStart(() =>
      {
        while (_socket != null)
        {
          try
          {
            var clientSocket = _socket.Accept();
            if (_clientSockets.Count <= maxListenQueue)
            {
              _clientSockets.Add(clientSocket);
            }
            else
            {
              clientSocket.Close();
            }
            Thread.Sleep(1);
          }
          catch
          {
            return;
          }
        }
      }))
      { IsBackground = true };
      thread.Start();
      return true;
    }

    /// <summary>
    /// 连接服务端
    /// </summary>
    public bool Connect()
    {
      this.Close();
      this.State = 0;
      _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
      _socket.SendTimeout = 3000;
      try
      {
        _socket.Connect(this.ServerIP, this.Port);
        //连接成功
        this.Connected = _socket.Connected;

        //在子线程中运行数据接收和接收异常处理
        var threadReciveData = new Thread(new ThreadStart(() =>
        {
          _socket.ReceiveBufferSize = 10240;
          _socket.Receive((json) => this.FireDataArrived(json), (exc) => this.FireError(exc));
          this.Connected = false;
        }))
        { IsBackground = true };
        threadReciveData.Start();
      }
      catch (Exception exc)
      {
        this.FireError(exc);
      }
      return this.Connected;
    }

    public void Close()
    {
      if (_socket != null)
      {
        if (this.State == 0)
        {
          if (_socket.Connected)
          {
            //关闭上一个连接
            try
            {
              _socket.Disconnect(false);
              _socket.Close();
            }
            catch { }
          }
        }
        else
        {
          try
          {
            _socket.Close();
            _socket = null;
          }
          catch { }
        }
        _socket = null;
      }
    }

    /// <summary>
    /// 发送数据
    /// </summary>
    /// <param name="jsonData"></param>
    public bool SendData(string jsonData)
    {
      if (this.State == 0)
      {
        return this.SendToServer(jsonData);
      }
      else
      {
        return this.SendToClients(jsonData);
      }
    }

    /// <summary>
    /// 作为客户端，将数据发送到服务端
    /// </summary>
    /// <param name="jsonData"></param>
    /// <returns></returns>
    protected bool SendToServer(string jsonData)
    {
      try
      {
        _socket.Send(jsonData);
        return true;
      }
      catch (Exception exc)
      {
        this.FireError(exc);
      }
      return false;
    }

    /// <summary>
    /// 作为服务端，将数据广播到客户端
    /// </summary>
    /// <param name="jsonData"></param>
    /// <returns></returns>
    protected bool SendToClients(string jsonData)
    {
      try
      {
        if (_clientSockets.IsNotNullOrEmpty())
        {
          var sockets = new ArrayList(_clientSockets.ToArray());
          sockets.Map<Socket>((client) =>
          {
            if (client == null)
            {
              return true;
            }
            if (client.Connected)
            {
              client.Send(jsonData);
            }
            else
            {
              try
              {
                _clientSockets.Remove(client);
                client.Close();
              }
              catch { }
            }
            return true;
          });
        }
        return true;
      }
      catch (Exception exc)
      {
        this.FireError(exc);
      }
      return false;
    }

    public bool SendData(object data)
    {
      return this.SendData(data.ToJSON());
    }

    public void Dispose()
    {
      this.Close();
    }
  }
}
